<?php
/**
 * Created by 无所谓已
 * User: Administrator
 * Date: 2025-08-16
 * Time: 21:57
 */

namespace plugin\csauto\app\service;

use plugin\csauto\app\model\DownloaderModel;
use plugin\csauto\app\model\TorrentTaskModel;
use plugin\csauto\app\model\TorrentListModel;
use support\Log;

/**
 * Class LoadBalancerService
 * 下载器负载均衡服务
 * @package plugin\csauto\app\service
 */
class LoadBalancerService
{
    /**
     * 获取最优下载器（负载均衡）
     * @return DownloaderModel|null
     */
    public static function getOptimalDownloader()
    {
        $downloaders = DownloaderModel::where('status', 1)->get();

        if ($downloaders->isEmpty()) {
            return null;
        }

        $downloaderLoads = [];

        foreach ($downloaders as $downloader) {
            $load = self::calculateLoad($downloader);
            $downloaderLoads[$downloader->id] = $load;
        }

        // 找到负载最小的下载器
        $minLoad = min($downloaderLoads);
        $optimalDownloaderId = array_search($minLoad, $downloaderLoads);

        return DownloaderModel::find($optimalDownloaderId);
    }

    /**
     * 计算下载器负载
     * @param DownloaderModel $downloader
     * @return float
     */
    public static function calculateLoad(DownloaderModel $downloader)
    {
        // 1. 计算当前活跃任务数量占比
        $activeTaskCount = TorrentTaskModel::where('downloader_id', $downloader->id)
            ->where('status', 1)
            ->count();

        $effectiveTaskLimit = $downloader->getEffectiveTaskLimit();
        $taskCountRatio = $effectiveTaskLimit > 0 ?
            min($activeTaskCount / $effectiveTaskLimit, 1.0) : 0;

        // 2. 计算当前容量使用占比
        $activeTasks = TorrentTaskModel::where('downloader_id', $downloader->id)
            ->where('status', '>=', 1)
            ->where('status', '<', 99)
            ->where('down_status', '>', 0)
            ->get();

        $currentSizeUsage = 0;
        foreach ($activeTasks as $task) {
            // 这里需要获取种子大小，可以通过TorrentListModel关联查询
            $torrent = TorrentListModel::where('site_id', $task->site_id)
                ->where('torrent_id', $task->torrent_id)
                ->first();

            if ($torrent) {
                $currentSizeUsage += HelperService::convertToGB($torrent->torrents_size);
            }
        }

        // 处理task_size为0或null的情况
        $taskSize = $downloader->task_size;
        if (empty($taskSize) || $taskSize <= 0) {
            $taskSize = 99999; // 设置一个很大的默认值，表示不限制容量
        }

        $sizeRatio = $taskSize > 0 ?
            min($currentSizeUsage / $taskSize, 1.0) : 0;

        // 3. 综合负载评分（加权平均）
        // 任务数量权重 60%，容量使用权重 40%
        $baseLoad = ($taskCountRatio * 0.6) + ($sizeRatio * 0.4);

        // 如果下载器被限速，增加负载权重（降低优先级）
        $throttlePenalty = $downloader->nc_throttled == 1 ? 0.3 : 0.0; // 限速时增加30%负载权重
        $totalLoad = min($baseLoad + $throttlePenalty, 1.0); // 最高不超过100%

        addlog('负载均衡', "下载器ID：{$downloader->id}, 任务数量：{$activeTaskCount}/{$effectiveTaskLimit}, 容量使用：{$currentSizeUsage}GB/{$taskSize}GB, 基础负载：{$baseLoad}, 限速惩罚：{$throttlePenalty}, 最终负载：{$totalLoad}");

        return $totalLoad;
    }

    /**
     * 获取所有下载器的负载状态
     * @return array
     */
    public static function getAllDownloaderLoads()
    {
        $downloaders = DownloaderModel::where('status', 1)->get();
        $loads = [];

        foreach ($downloaders as $downloader) {
            $loads[$downloader->id] = [
                'downloader' => $downloader,
                'load' => self::calculateLoad($downloader),
                'active_tasks' => TorrentTaskModel::where('downloader_id', $downloader->id)->where('status', 1)->count(),
                'capacity_usage' => self::getCapacityUsage($downloader)
            ];
        }

        return $loads;
    }

    /**
     * 获取下载器容量使用情况
     * @param DownloaderModel $downloader
     * @return array
     */
    private static function getCapacityUsage(DownloaderModel $downloader)
    {
        $activeTasks = TorrentTaskModel::where('downloader_id', $downloader->id)
            ->where('status', '>=', 1)
            ->where('status', '<', 99)
            ->where('down_status', '>', 0)
            ->get();

        $currentSizeUsage = 0;
        $taskSizes = [];

        foreach ($activeTasks as $task) {
            $torrent = TorrentListModel::where('site_id', $task->site_id)
                ->where('torrent_id', $task->torrent_id)
                ->first();

            if ($torrent) {
                $sizeGB = HelperService::convertToGB($torrent->torrents_size);
                $currentSizeUsage += $sizeGB;
                $taskSizes[] = [
                    'torrent_id' => $task->torrent_id,
                    'size_gb' => $sizeGB
                ];
            }
        }

        // 处理task_size为0或null的情况
        $taskSize = $downloader->task_size;
        if (empty($taskSize) || $taskSize <= 0) {
            $taskSize = 99999; // 设置一个很大的默认值，表示不限制容量
        }

        return [
            'used' => $currentSizeUsage,
            'total' => $taskSize,
            'percentage' => $taskSize > 0 ? ($currentSizeUsage / $taskSize) * 100 : 0,
            'tasks' => $taskSizes
        ];
    }

    /**
     * 获取所有可用的下载器（按负载排序）
     * @param int $maxCount 最大返回数量（0表示返回所有）
     * @param float $maxLoadThreshold 最大负载阈值（0.0-1.0），超过此值的下载器不返回
     * @return array 返回包含下载器和负载信息的数组
     */
    public static function getAvailableDownloaders($maxCount = 0, $maxLoadThreshold = 0.95)
    {
        $downloaders = DownloaderModel::where('status', 1)->get();

        if ($downloaders->isEmpty()) {
            return [];
        }

        $availableDownloaders = [];

        foreach ($downloaders as $downloader) {
            $load = self::calculateLoad($downloader);
            
            // 过滤掉负载过高的下载器
            if ($load < $maxLoadThreshold) {
                $availableDownloaders[] = [
                    'downloader' => $downloader,
                    'load' => $load,
                    'id' => $downloader->id
                ];
            }
        }

        // 按负载从低到高排序
        usort($availableDownloaders, function($a, $b) {
            return $a['load'] <=> $b['load'];
        });

        // 如果指定了最大数量，则只返回前N个
        if ($maxCount > 0) {
            $availableDownloaders = array_slice($availableDownloaders, 0, $maxCount);
        }

        return $availableDownloaders;
    }

    /**
     * 计算下载器可以接受的任务数量
     * @param DownloaderModel $downloader
     * @return int 可接受的任务数量
     */
    public static function getAvailableTaskSlots(DownloaderModel $downloader)
    {
        $taskCount = TorrentTaskModel::where('downloader_id', $downloader->id)
            ->where('status', 1)
            ->count();
        
        $effectiveTaskLimit = $downloader->getEffectiveTaskLimit();
        
        return max(0, $effectiveTaskLimit - $taskCount);
    }
}
